package org.quipu.client;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import java.util.HashMap;
import java.util.Map;
import org.quipu.client.events.AppEvent;
import org.quipu.client.events.AppEventBus;
import org.quipu.client.events.AppEventListener;
import org.quipu.client.events.BooksOutOfDateEvent;
import org.quipu.client.events.BookChangedEvent;
import org.quipu.dto.BookDto;

public class BookEditPanel extends AppEventWidget implements AppEventListener {

    private final VerticalPanel vPanel;
    private final FlexTable table;
    private final TextBox editBox;
    private final Button submitBtn;
    private final Button removeBtn;
    private final Map<Integer, BookDto> bookRowCache;
    private Long selectedBookId;

    public BookEditPanel(AppEventBus eventBus, AppCache cache) {
        super(eventBus, cache);
        bookRowCache = new HashMap<Integer, BookDto>();

        vPanel = new VerticalPanel();
        vPanel.addStyleName("controlPanel");
        editBox = new TextBox();
        editBox.addStyleName("titleInput");
        submitBtn = new Button("Создать");
        submitBtn.addClickHandler(new ClickHandler() {

            public void onClick(ClickEvent event) {
                submitBook();
            }
        });
        removeBtn = new Button("Удалить");
        removeBtn.addClickHandler(new ClickHandler() {

            public void onClick(ClickEvent event) {
                removeBook();
            }
        });
        table = new FlexTable();
        table.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                Cell cell = table.getCellForEvent(event);
                int row = cell.getRowIndex();
                selectBook(row);
            }
        });
        vPanel.add(table);
    }

    @Override
    public void init() {
        getEventBus().addListener(BooksOutOfDateEvent.class, this);
    }

    @Override
    public Widget getWidget() {
        return vPanel;
    }

    @Override
    public void handleEvent(AppEvent event) {
        if(event != null) {
            if(event instanceof BooksOutOfDateEvent) {
                refresh();
            }
        }
    }

    private void refresh() {
        table.removeAllRows();
        int row = 0;
        FlexTable.FlexCellFormatter cellFormatter = table.getFlexCellFormatter();
        FlexTable.RowFormatter rowFormatter = table.getRowFormatter();
        bookRowCache.clear();
        boolean selected = false;
        for(BookDto book: getCache().getBooks()) {
            table.setWidget(row, 0, new Label(book.getTitle()));
            cellFormatter.setColSpan(row, 0, 2);
            if(selectedBookId != null && book.getId().equals(selectedBookId)) {
                rowFormatter.addStyleName(row, "tableSelectedRow");
                selected = true;
            }
            rowFormatter.addStyleName(row, "tableSelectableRow");
            bookRowCache.put(row, book);
            row++;
        }
        table.setWidget(row, 0, editBox);
        table.setWidget(row++, 1, submitBtn);
        if(!selected) {
            selectedBookId = null;
        } else {
            table.setWidget(row, 1, removeBtn);
        }
    }

    private void selectBook(int row) {
        BookDto book = bookRowCache.get(row);
        if(book != null) {
            if(book.getId().equals(selectedBookId)) {
                selectedBookId = null;
            } else {
                selectedBookId = book.getId();
            }
            BookDto selectedBook = getCache().getBook(selectedBookId);
            editBox.setValue(selectedBook == null? "": selectedBook.getTitle());
            submitBtn.setText(selectedBookId == null? "Создать": "Сохранить");
            refresh();
        }
    }

    private void removeBook() {
        getMainService().removeBook(selectedBookId, new AsyncCallback<Void>() {

            public void onSuccess(Void result) {
                getEventBus().fireEvent(new BookChangedEvent(BookEditPanel.this, null));
            }

            public void onFailure(Throwable caught) {
                Window.alert(caught.getMessage());
            }
        });
    }

    private void submitBook() {
        final BookDto book = new BookDto();
        if(selectedBookId != null) {
            book.setId(selectedBookId);
        }
        book.setTitle(editBox.getValue());
        getMainService().submitBook(book, new AsyncCallback<Void>() {

            public void onSuccess(Void result) {
                getEventBus().fireEvent(new BookChangedEvent(BookEditPanel.this, book));
            }

            public void onFailure(Throwable caught) {
                Window.alert(caught.getMessage());
            }
        });
    }
}
